package net.j4love.nio.quickstart;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * @author He Peng
 * @create 2017-07-29 1:16
 * @update 2017-07-29 1:16
 * @updatedesc : 更新说明
 * @see
 */
public class NIOEchoServerClient {

    private static final boolean BLOCKING = true;
    private static final boolean NON_BLOCKING = false;
    private SocketChannel socketChannel;
    private Selector selector;

    public static void main(String[] args) throws IOException {
        NIOEchoServerClient echoServerClient = new NIOEchoServerClient();
        echoServerClient.connect("127.0.0.1",8080);
        echoServerClient.communicate();
    }

    public void connect(String host,int port) throws IOException {
        this.socketChannel = SocketChannel.open();
        this.socketChannel.configureBlocking(false);
        this.selector = Selector.open();
        this.socketChannel.register(this.selector, SelectionKey.OP_CONNECT);
        this.socketChannel.connect(new InetSocketAddress(host,port));
    }

    public void communicate() throws IOException {
        while (null != this.socketChannel
                && null != this.selector
                && this.selector.isOpen()) {
            int select = this.selector.select(500);
            if (select == 0) {
                continue;
            }

            Iterator<SelectionKey> iterator = this.selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                iterator.remove();
                if (selectionKey.isConnectable()) {
                    System.out.println("The connection is ready");
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    if (! socketChannel.isConnected()) {
                        socketChannel.finishConnect();
                    }
                    socketChannel.configureBlocking(NON_BLOCKING);
                    socketChannel.register(this.selector,SelectionKey.OP_WRITE);
                } else if (selectionKey.isReadable()) {
                    System.out.println("SocketChannel Read is ready");
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    ByteBuffer bBuf = ByteBuffer.allocateDirect(1024 * 2);
                    socketChannel.read(bBuf);
                    bBuf.flip();
                    byte[] dst = new byte[bBuf.limit()];
                    bBuf.get(dst,0,dst.length);
                    String body = new String(dst,"utf-8");
                    System.out.println("Received server data : " + body);

                    socketChannel.close();
                } else if (selectionKey.isWritable()) {
                    System.out.println("write to server");
                    ByteBuffer buffer = ByteBuffer.allocate(1024 * 2);
                    SocketChannel channel = (SocketChannel) selectionKey.channel();
                    channel.configureBlocking(NON_BLOCKING);
                    channel.register(this.selector,SelectionKey.OP_READ);

                    buffer.put("你好 server！".getBytes("utf-8"));
                    buffer.flip();
                    channel.write(buffer);
                }
            }
        }
    }
}
